package com.tanhua.dubbo.server.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Service;
import com.mongodb.client.result.DeleteResult;
import com.sun.org.apache.regexp.internal.RE;
import com.tanhua.dubbo.server.pojo.Comment;
import com.tanhua.dubbo.server.pojo.FollowUser;
import com.tanhua.dubbo.server.pojo.Publish;
import com.tanhua.dubbo.server.pojo.Video;
import com.tanhua.dubbo.server.service.IdService;
import com.tanhua.dubbo.server.vo.CommentType;
import com.tanhua.dubbo.server.vo.IdType;
import com.tanhua.dubbo.server.vo.PageInfo;
import com.tanhua.dubbo.server.vo.SortRule;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;

@Service(version = "1.0.0")
@Slf4j
public class VideoApiImpl implements VideoApi {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private IdService idService;
    @Autowired
    private QuanZiApi quanZiApi;

    private static final String VIDEO_FOLLOW_USER_KEY_PREFIX = "VIDEO_FOLLOW_USER_";

    public static String getVideoFollowUserKeyPrefix(Long userId) {
        return VIDEO_FOLLOW_USER_KEY_PREFIX + userId;
    }

    /**
     * 关注用户
     *
     * @param userId       当前用户
     * @param followUserId 关注的目标用户
     * @return
     */
    @Override
    public Boolean followUser(Long userId, Long followUserId) {
        if (!ObjectUtil.isAllNotEmpty(userId, followUserId)) {
            return false;
        }
        //1.用户是否关注小视频用户
        if (this.isFollowUser(userId, followUserId)) {
            return false;
        }
        FollowUser followUser = new FollowUser();
        followUser.setCreated(System.currentTimeMillis());
        followUser.setId(ObjectId.get());
        followUser.setUserId(userId);
        followUser.setFollowUserId(followUserId);
        FollowUser save = mongoTemplate.save(followUser);
        if (save == null) {
            return false;
        }
        String redisKey = getVideoFollowUserKeyPrefix(userId);
        String hashKey = String.valueOf(followUserId);
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");
        return true;
    }

    /**
     * 取消关注用户
     *
     * @param userId       当前用户
     * @param followUserId 关注的目标用户
     * @return
     */
    @Override
    public Boolean disFollowUser(Long userId, Long followUserId) {
        if (!ObjectUtil.isAllNotEmpty(userId, followUserId)) {
            return false;
        }
        //1.用户是否关注小视频用户
        if (!this.isFollowUser(userId, followUserId)) {
            return false;
        }
        Query query = Query.query(Criteria.where("userId").is(userId).and("followUserId").is(followUserId));
        DeleteResult deleteCount = mongoTemplate.remove(query, FollowUser.class);
        if (deleteCount.getDeletedCount() > 0) {
            String redisKey = getVideoFollowUserKeyPrefix(userId);
            String hashKey = String.valueOf(followUserId);
            redisTemplate.opsForHash().delete(redisKey, hashKey);
            return true;
        }
        return false;
    }

    /**
     * 查询用户是否关注某个用户
     *
     * @param userId       当前用户
     * @param followUserId 关注的目标用户
     * @return
     */
    @Override
    public Boolean isFollowUser(Long userId, Long followUserId) {
        String redisKey = getVideoFollowUserKeyPrefix(userId);
        String hashKey = String.valueOf(followUserId);
        return redisTemplate.opsForHash().hasKey(redisKey, hashKey);
    }

    /**
     * 实现功能:获取系统推荐的所有小视频
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public List<Video> findAllVideos(Long userId, Integer page, Integer pageSize) {
        List<Video> videoList = new ArrayList<>();
        String redisKey = "QUANZI_VIDEO_RECOMMEND_" + userId;
        String data = redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isNotEmpty(data)) {
            List<String> vIds = StrUtil.split(data, ',');
            int[] ints = PageUtil.transToStartEnd(page - 1, pageSize);
            List<Long> findVIds = new ArrayList<>();
            for (int i = ints[0]; i < Math.min(ints[1], vIds.size()); i++) {
                findVIds.add(Long.valueOf(vIds.get(i)));
            }
            Query querys = Query.query(Criteria.where("vid").in(findVIds)).with(Sort.by(Sort.Order.desc("created")));
            videoList = mongoTemplate.find(querys, Video.class);
            if (ints[1] > vIds.size()) {
                //查找自己的视频库,系统不满足查找条件找自己的视频库
                List<Video> videos = new ArrayList<>();
                if (ints[0] < vIds.size()) {
                    Query query = Query.query(Criteria.where("userId").is(userId)).limit(ints[1] - vIds.size()).with(Sort.by(Sort.Order.desc("created")));
                    videos = mongoTemplate.find(query, Video.class);
                } else {
                    int skip = ints[0] - vIds.size();
                    Query query = Query.query(Criteria.where("userId").is(userId)).skip(skip).limit(pageSize).with(Sort.by(Sort.Order.desc("created")));
                    videos = mongoTemplate.find(query, Video.class);
                }
                for (Video video : videos) {
                    if (CollUtil.isEmpty(videoList)) {
                        videoList = new ArrayList<>();
                    }
                    videoList.add(video);
                }
            }
        }
        return videoList;
    }

    /**
     * 实现功能:保存小视频
     *
     * @param video
     * @return
     */
    @Override
    public String saveVideo(Video video) {
        try {
            video.setId(ObjectId.get());
            video.setVid(idService.creatIncrement(IdType.VIDEO));
            video.setCreated(System.currentTimeMillis());
            Video save = mongoTemplate.save(video);
            return save.getId().toHexString();
        } catch (Exception e) {
            return null;
        }
    }



    /**
     * 获取所有的视频信息
     * @param page
     * @param pageSize
     * @param sortProp
     * @param sortOrder
     * @param uid
     * @return
     */
    @Override
    public PageInfo<Video> findAllVideoBackstage(Integer page, Integer pageSize, String sortProp, String sortOrder, Long uid) {
        //创建结果对象
        PageInfo<Video> pageInfo = new PageInfo<>();
        //封装属性
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        //创建查询总条数的条件
        Query queryCount = Query.query(Criteria.where("userId").is(uid));
        pageInfo.setTotal(Convert.toInt(mongoTemplate.count(queryCount, Video.class)));


        //判断是否按时间排序
        if ("createDate".equals(sortProp)) {
            PageRequest pageRequest = null;
            //是否升序
            if (StrUtil.equals("ascending", sortOrder)) {
                //升序
                pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.asc("created")));
            } else {
                //降序
                pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));
            }
            //创建查询视频信息条件
            Query query = Query.query(Criteria.where("userId").is(uid)).with(pageRequest);
            //获取符合条件的视频信息
            List<Video> videos = mongoTemplate.find(query, Video.class);
            pageInfo.setRecords(videos);
            //返回结果对象
            return pageInfo;
        } else {
            List<Video> commentLists = null;
            switch (sortProp) {
                case "reportCount":
                    //查询按举报数排序的视频结果
                    commentLists = this.getCommentLists(uid, CommentType.REPORT);
                    break;

                case "likeCount":
                    //查询按点赞数排序的视频结果
                    commentLists = this.getCommentLists(uid, CommentType.LIKE);
                    break;
                case "commentCount":
                    //查询按评论数排序的视频结果
                    commentLists = this.getCommentLists(uid, CommentType.COMMENT);
                    break;
                case "forwardingCount":
                    //查询按转发数排序的视频结果
                    commentLists = this.getCommentLists(uid, CommentType.TRANSMIT);
                    break;
            }
            if (StrUtil.equals("ascending", sortOrder)) {
                //升序的直接返回结果集
                //手动分页
                int[] ints = PageUtil.transToStartEnd(page - 1, pageSize);
                List<Video> videoLs = new ArrayList<>();
                for (int i = ints[0]; i < Math.min(commentLists.size(), ints[1]); i++) {
                    videoLs.add(commentLists.get(i));
                }
                //返回结果信息
                pageInfo.setRecords(videoLs);
                return pageInfo;
            } else {
                List<Video> videoList = new ArrayList<>();
                //降序的需要将集合反转
                for (int i = commentLists.size() - 1; i >= 0; i--) {
                    Video video = commentLists.get(i);
                    videoList.add(video);
                }
                //手动分页
                int[] ints = PageUtil.transToStartEnd(page - 1, pageSize);
                List<Video> videoLs = new ArrayList<>();
                for (int i = ints[0]; i < Math.min(videoList.size(), ints[1]); i++) {
                    videoLs.add(videoList.get(i));
                }
                pageInfo.setRecords(videoLs);
                //返回结果信息
                return pageInfo;
            }
        }
    }



    /**
     * 获取视频列表信息
     * @param userId
     * @param type
     * @return
     */
    public List<Video> getCommentLists(Long userId, CommentType type) {
        //创建集合
        List<Video> list = new ArrayList<>();
        //根据查询条件(根据用户id查询)获取视频信息
        Query query = Query.query(Criteria.where("userId").is(userId));
        List<Video> videos = mongoTemplate.find(query, Video.class);
        //创建SortRule对象的集合
        TreeSet<SortRule> sortRules = new TreeSet<>(new Comparator<SortRule>() {
            @Override
            //升序排序对象按照数量主要,id次要
            public int compare(SortRule o1, SortRule o2) {
                return Convert.toInt(o1.getCount() - o2.getCount()) == 0 ? (o1.getId().compareTo(o2.getId())) : Convert.toInt(o1.getCount() - o2.getCount());
            }
        });
        for (Video video : videos) {
            //查询评论,点赞,举报,转发数量
            Long aLong = quanZiApi.likeAndLoveCount(userId, video.getId().toHexString(), type);
            if (ObjectUtil.isEmpty(aLong)) {
                aLong = Convert.toLong(0);
            }
            //创建SortRule对象
            SortRule sortRule = new SortRule();
            sortRule.setId(video.getId());
            sortRule.setCount(aLong);
            sortRules.add(sortRule);
        }
        //对排序的视频,根据id获取视频信息
        for (SortRule sortRule : sortRules) {
            Query queryOne = Query.query(Criteria.where("id").is(sortRule.getId()));
            list.add(mongoTemplate.findOne(queryOne, Video.class));
        }
        return list;
    }

    /**
     * 获取动态信息
     * @param userId
     * @param type
     * @return
     */
    public List<Publish> getPublishCommentLists(Long userId, CommentType type) {
        //创建集合
        List<Publish> list = new ArrayList<>();
        //根据查询条件(根据用户id查询)获取视频信息
        Query query = Query.query(Criteria.where("userId").is(userId));
        List<Publish> publishes = mongoTemplate.find(query, Publish.class);
        //创建SortRule对象的集合
        TreeSet<SortRule> sortRules = new TreeSet<>(new Comparator<SortRule>() {
            //升序排序对象按照数量主要,id次要
            @Override
            public int compare(SortRule o1, SortRule o2) {
                return Convert.toInt(o1.getCount() - o2.getCount()) == 0 ? (o1.getId().compareTo(o2.getId())) : Convert.toInt(o1.getCount() - o2.getCount());
            }
        });
        for (Publish publish : publishes) {
            //查询评论,点赞,举报,转发数量
            Long aLong = quanZiApi.likeAndLoveCount(userId, publish.getId().toHexString(), type);
            if (ObjectUtil.isEmpty(aLong)) {
                aLong = Convert.toLong(0);
            }
            //创建SortRule对象
            SortRule sortRule = new SortRule();
            sortRule.setId(publish.getId());
            sortRule.setCount(aLong);
            sortRules.add(sortRule);
        }
        //对排序的视频,根据id获取视频信息
        for (SortRule sortRule : sortRules) {
            Query queryOne = Query.query(Criteria.where("id").is(sortRule.getId()));
            list.add(mongoTemplate.findOne(queryOne, Publish.class));
        }
        return list;
    }


}
